package com.huidu.bitrade.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huidu.bitrade.constant.SysConstant;
import com.huidu.bitrade.constant.TransactionType;
import com.huidu.bitrade.dao.MemberDao;
import com.huidu.bitrade.dto.*;
import com.huidu.bitrade.entity.*;
import com.huidu.bitrade.entity.transform.AuthMember;
import com.huidu.bitrade.exception.ServiceException;
import com.huidu.bitrade.mapper.AcAwardConfigMapper;
import com.huidu.bitrade.mapper.AcMemberMapper;
import com.huidu.bitrade.enums.ChargeRecommendEnum;
import com.huidu.bitrade.enums.MemberStarEnum;
import com.huidu.bitrade.mapper.MemberMapper;
import com.huidu.bitrade.enums.StarChargeEnum;
import com.huidu.bitrade.vo.*;
import com.google.common.collect.Maps;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 购买份数
 */
@Service
@Slf4j
public class AcMemberService{

    @Autowired
    private MemberDao memberDao;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    @Qualifier("DefaultPurchaseService")
    private PurchaseService defaultPurchaseService;
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    @Qualifier("defaultAcHdcAwardService")
    private AcHdcAwardService hdcAwardService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LocaleMessageSourceService msService;
    @Autowired
    private AcMemberMapper acMemberMapper;
    @Autowired
    @Qualifier("defaultAcChargeHdcAwardService")
    private AcChargeHdcAwardService acChargeHdcAwardService;
    @Autowired
    private AcGroupChargeAwardService acGroupChargeAwardService;
    @Autowired
    private NewMemberService newMemberService;
    @Autowired
    private AcAwardConfigMapper acAwardConfigMapper;
    private final Logger logger = LoggerFactory.getLogger("member-task");

    /**
     * 获取用户当前购买的份数
     * @param authMember
     * @return
     */
    public Integer getCurrCount(AuthMember authMember){
        Member member = memberDao.getOne(authMember.getId());
        return Objects.nonNull(member.getMemberStar()) ? member.getMemberStar() : 0;
    }

    /**
     * 购买
     * @param count 购买份数，对应 {@link MemberStarEnum}中的份数
     * @param payType 支付方式 1、币本位hdz 70%，金本位cnhd 30%  2、金本位购买
     * @return
     */
    public boolean purchase(AuthMember authMember,Integer count, Integer payType) throws ServiceException {
        //查询hdz价格
        BigDecimal currentHdz = getCurrentHdz();
//        //需求：hdz价格小于5000必须双币组合，不能为单币支付
//        if(currentHdz.compareTo(BigDecimal.valueOf(5000)) < 0 && payType == 2){
//            throw new IllegalArgumentException(msService.getMessage("HDZ_THE_PRICE_HAS_CHANGED_PLEASE_REFRESH_AND_TRY_AGAIN"));
//        }
        Member member = memberService.findOne(authMember.getId());
        authMember.setMemberStarEnum(MemberStarEnum.get(member.getMemberStarCount()));

        //count需要购买的份数 - 查询当前用户购买的份数
        Integer memberStarCount = Objects.isNull(member.getMemberStarCount()) ? 0 : member.getMemberStarCount();
        //需要购买的份数
        Integer purchaseCount = count - memberStarCount;

        MemberStarEnum starEnum = MemberStarEnum.get(count);
        long countByMemberStar = memberDao.findCountByMemberStar(starEnum.getLevel());
        Assert.isTrue(countByMemberStar < starEnum.getMaxPeople(),msService.getMessage("THIS_STAR_RATING_IS_FULL"));
        Assert.isTrue(count > (Objects.isNull(member.getMemberStarCount()) ? 0 : member.getMemberStarCount()),msService.getMessage("ONLY_NODES_LARGER_THAN_THE_CURRENT_ONE_CAN_BE_PURCHASED"));
        return defaultPurchaseService.purchaseFunction(authMember, starEnum,purchaseCount, payType,currentHdz);
    }

    /**
     * 购买星级，仅用于导入用户星级数据使用
     * @return
     */
    public boolean purchaseImport(Member member,Integer count, Integer payType) throws ServiceException {
        //查询hdz价格
        BigDecimal currentHdz = BigDecimal.valueOf(2000);
        AuthMember authMember = AuthMember.toAuthMember(member);
        authMember.setMemberStarEnum(MemberStarEnum.get(member.getMemberStarCount()));
        //count需要购买的份数 - 查询当前用户购买的份数
        Integer memberStarCount = Objects.isNull(member.getMemberStarCount()) ? 0 : member.getMemberStarCount();
        //需要购买的份数
        Integer purchaseCount = count - memberStarCount;

        MemberStarEnum starEnum = MemberStarEnum.get(count);
        long countByMemberStar = memberDao.findCountByMemberStar(starEnum.getLevel());
        Assert.isTrue(countByMemberStar < starEnum.getMaxPeople(),msService.getMessage("THIS_STAR_RATING_IS_FULL"));
        Assert.isTrue(count > (Objects.isNull(member.getMemberStarCount()) ? 0 : member.getMemberStarCount()),msService.getMessage("ONLY_NODES_LARGER_THAN_THE_CURRENT_ONE_CAN_BE_PURCHASED"));
        return defaultPurchaseService.purchaseFunctionImport(authMember, starEnum,purchaseCount, payType,currentHdz);
    }

    /**
     * hdc奖励
     */
    public void hdcAward(){
        logger.info("=========发放hdc奖励开始=======");
        //获得星级和单份数量
        Map<Integer, Data> algorithmMap = getAlgorithm();
        //有星级的用户
        List<Member> memberList = memberMapper.selectList(Wrappers.<Member>lambdaQuery()
                .select(Member::getId,Member::getMemberStar,Member::getMemberStarCount)
                .isNotNull(Member::getMemberStar));

        OtcCoin otcCoin = new OtcCoin();
        otcCoin.setUnit("HDC");
        for (Member member : memberList) {
            logger.info("=========发放hdc奖励用户=======memberId{}",member.getId());
            //计算奖励
            Data data = algorithmMap.get(member.getMemberStar());
            BigDecimal award = data.getUnitNumber().multiply(BigDecimal.valueOf(member.getMemberStarCount()));
            logger.info("=========发放奖励=======award{}",award+"="+data.getUnitNumber()+"*"+member.getMemberStarCount());
            MemberWallet memberWallet = memberWalletService.findByOtcCoinAndMemberId(otcCoin, member.getId());
            //创建事务发放
            transactionTemplate.execute((TransactionCallback) transactionStatus -> {
                try {
                    String fail = null;
                    int status = 1;
                    if(Objects.isNull(memberWallet)){
                        fail ="用户没有HDC钱包";
                        status = 0;
                    }else{
                        memberWalletService.operateIncreaseBalance(memberWallet,award, TransactionType.ACTIVITY_AWARD);
                    }
                    //存储hdc奖励
                    hdcAwardService.save(AcHdcAward.builder()
                            .memberId(member.getId())
                            .fail(fail)
                            .status(status)
                            .memberStarPeople(data.getPeople())
                            .memberStar(member.getMemberStar())
                            .unitNumber(data.getUnitNumber())
                            .count(data.getCount())
                            .sumAwardNumber(data.getSumAwardNumber())
                            .sumCount(data.getSumCount())
                            .awardHdc(data.getUnitNumber().multiply(BigDecimal.valueOf(data.getCount()).setScale(8,RoundingMode.DOWN)))
                            .build());
                    logger.info("=========发放hdc用户奖励完成=======memberId{}",member.getId());
                    return true;
                } catch (Exception exception) {
                    logger.info("执行事务异常，需要回滚");
                    transactionStatus.setRollbackOnly();
                    return false;
                }
            });
        }
        logger.info("=========发放hdc奖励完成=======");
    }

    /**
     * 获得当前hdz价格
     * @return
     */
    public BigDecimal getCurrentHdz(){
        //获取hdz价格
        String exchangeUrl = "http://BITRADE-MARKET/market/getSymbolThumb?symbol=HDZ/CNHD";
        try {
            ResponseEntity<HashMap> response = restTemplate.getForEntity(exchangeUrl, HashMap.class);
            Map<String, Object> responseData = (HashMap<String, Object>)response.getBody();
            log.info("调用HDZ行情接口响应：{}",response);
            log.info("调用HDZ行情接口响应体：{}",responseData);
            //处理接口异常
            if(Objects.isNull(responseData)){
                throw new IllegalArgumentException(msService.getMessage("THE_SERVICE_INTERFACE_DOES_NOT_QUERY_THE_DATA"));
            }
            Object codeObj = responseData.get("code");
            if(Objects.nonNull(codeObj)){
                log.error("服务接口查询数据失败，返回数据:{}",responseData);
                throw new IllegalArgumentException(msService.getMessage("SERVICE_INTERFACE_FAILED_TO_QUERY_DATA"));
            }
            Object closeObj = responseData.get("close");
            if(Objects.isNull(closeObj)){
                throw new IllegalArgumentException(msService.getMessage("NO_DATA_PARSED"));
            }
            //处理接口异常处理结束====
            //类型处理
            BigDecimal volume =BigDecimal.ZERO;
            if(closeObj instanceof Integer){
                volume = BigDecimal.valueOf((Integer) closeObj);
            }else if(closeObj instanceof Double){
                volume = BigDecimal.valueOf((Double) closeObj);
            }
            //类型处理结束
            if(volume.compareTo(BigDecimal.valueOf(0)) <= 0){
                throw new IllegalArgumentException(msService.getMessage("FAILED_TO_GET_DATA_PLEASE_TRY_AGAIN"));
            }
            return volume;
        }catch (Exception e){
            if(!(e instanceof IllegalArgumentException)){
                log.error("获取hdz行情异常",e);
                throw new IllegalArgumentException(msService.getMessage("FAILED_TO_CALL_SERVICE_INTERFACE"));
            }
        }
        return BigDecimal.valueOf(0);
    }

    /**
     * 获得星级和单份数量
     * @return
     */
    private Map<Integer,Data> getAlgorithm(){
        //每天释放的hdc奖励总数量
        BigDecimal hdcToday = BigDecimal.valueOf(3800);
        List<MemberStarCountDTO> memberCountList = memberMapper.findMemberCount();
        Map<Integer,Data> map = Maps.newConcurrentMap();
        AtomicReference<Data> data = new AtomicReference<>();


//        MemberStarEnum[] values = MemberStarEnum.values();
//        for (MemberStarEnum memberStarEnum : values) {
//            //总份数计算，每个节点人数 * 该节点份数
//            BigDecimal multiply = BigDecimal.valueOf(memberStarEnum.getMaxPeople()).multiply(BigDecimal.valueOf(memberStarEnum.getCount()));
//            //单份数量，奖励总数量/总份数
//            BigDecimal unitNumber = hdcToday.divide(multiply,8,RoundingMode.DOWN);
//
//            data.set(Data.builder()
//                    .people(memberStarEnum.getMaxPeople())
//                    .count(memberStarEnum.getCount())
//                    .sumCount(multiply)
//                    .sumAwardNumber(hdcToday)
//                    .unitNumber(unitNumber)
//                    .build());
//            //单数数量，是根据星级算出来的，所以算个人奖励需要知道对应的星级是什么，再根据这个星级的单份数量 * 他个人对应的数量
//            map.put(memberStarEnum.getLevel(),data.get());
//        }


        memberCountList.forEach(memberCount->{
            //根据星级获得枚举
            MemberStarEnum memberStarEnum = MemberStarEnum.getByLevel(memberCount.getMemberStar());
            //总份数计算，每个节点人数 * 该节点份数
            BigDecimal multiply = BigDecimal.valueOf(memberCount.getPepole()).multiply(BigDecimal.valueOf(memberStarEnum.getCount()));
            //单份数量，奖励总数量/总份数
//            BigDecimal unitNumber = hdcToday.divide(multiply,8,RoundingMode.DOWN);
            data.set(Data.builder()
                    .people(memberCount.getPepole())
                    .count(memberStarEnum.getCount())
                    .sumCount(multiply)
                    .sumAwardNumber(hdcToday)
//                    .unitNumber(unitNumber)
                    .build());
            //单数数量，是根据星级算出来的，所以算个人奖励需要知道对应的星级是什么，再根据这个星级的单份数量 * 他个人对应的数量
            map.put(memberStarEnum.getLevel(),data.get());
        });

        //添加金额
        BigDecimal sum = BigDecimal.ZERO;
        for (Map.Entry<Integer, Data> dataEntry : map.entrySet()) {
            Data value = dataEntry.getValue();
            sum = sum.add(value.sumCount);
        }

        Map<Integer,Data> newMap = Maps.newHashMap();
        for (Map.Entry<Integer, Data> dataEntry : map.entrySet()) {
            Data value = dataEntry.getValue();
            BigDecimal unitNumber = hdcToday.divide(sum,8,RoundingMode.DOWN);
            value.setUnitNumber(unitNumber);
            newMap.put(dataEntry.getKey(), value);
        }
        return newMap;
    }

    @lombok.Data
    @Builder
    static class Data{
        //节点（星）类型人数
        private Integer people;
        //该节点对应的份数（星级对应的份数）
        private Integer count;
        //总份数
        private BigDecimal sumCount;
        //奖励总数量
        private BigDecimal sumAwardNumber;
        //单份数量(奖励总数量/总份数)
        private BigDecimal unitNumber;
    }

    public List<RankNumberDTO> getRankNumber() {
        return acMemberMapper.getRankNumber();
    }


    public IPage<AcMemberStarRecordVo> getMemberStarRecordVos(IPage page, AcMemberQuery acMemberQuery) {
        return page.setRecords(acMemberMapper.getMemberStarRecordVos(page,acMemberQuery));
    }


    public IPage<AcHdcAwardVO> getHdcRecord(IPage page, AcMemberQuery acMemberQuery) {
        return page.setRecords(acMemberMapper.getHdcRecord(page,acMemberQuery));
    }


    public IPage<AcMemberRecordVo> getMemberRecord(IPage page, AcMemberRecordDTO memberRecordDTO) {
        List<AcMemberRecordVo> memberRecords = acMemberMapper.getMemberRecord(page,memberRecordDTO);
        for (AcMemberRecordVo acMemberRecordVo : memberRecords) {
            String[] newType = acMemberRecordVo.getQuantity().split(",");
            Double cnhd = Double.valueOf(newType[0]);
            Double hdz = newType.length>1 ? Double.valueOf(newType[1]) : 0.0;
            acMemberRecordVo.setHdz(BigDecimal.valueOf(hdz));
            acMemberRecordVo.setCnhd(BigDecimal.valueOf(cnhd));
            acMemberRecordVo.setType(newType.length > 1 ? "组合" : "金本位");
        }
        return page.setRecords(memberRecords);
    }

    public IPage<AcReferrerRewardsVO> getRewards(IPage page, @Param("param") AcReferrerRewardsDTO acReferrerRewardsDTO){
        return page.setRecords(acMemberMapper.getRewards(page,acReferrerRewardsDTO));
    }

    /**
     * hdc 手续费奖励
     */
    public void chargeHdcAward(){
        logger.info("========开始发放hdc手续费奖励========");
        //有星级的用户
        List<Member> memberList = memberMapper.selectList(Wrappers.<Member>lambdaQuery()
                .select(Member::getId,Member::getMemberStar,Member::getMemberStarCount)
                .isNotNull(Member::getMemberStar));
        if(CollectionUtils.isEmpty(memberList)){
            logger.info("未查询到有星级的用户");
            return;
        }
        //获得星级和单份数量
        Map<Integer, ChargeData> algorithmMap = getStarRatioData();
        OtcCoin otcCoin = new OtcCoin();
        otcCoin.setUnit("HDC");
        for (Member member : memberList) {
            logger.info("==========发放用户hdc手续费奖励========member_id{}",member.getId());
            //计算奖励
            ChargeData data = algorithmMap.get(member.getMemberStar());
            BigDecimal award = data.getUnitNumber();
            logger.info("==========奖励数量========award{}",award);
            logger.info("==========奖励比例========level{}",data.getRatio());
            logger.info("==========总人数========people{}",data.getPeople());
            MemberWallet memberWallet = memberWalletService.findByOtcCoinAndMemberId(otcCoin, member.getId());
            //创建事务发放
            transactionTemplate.execute((TransactionCallback) transactionStatus -> {
                try {
                    String fail = null;
                    int status = 1;
                    if(Objects.isNull(memberWallet)){
                        fail ="用户没有HDC钱包";
                        status = 0;
                    }else{
                        memberWalletService.operateIncreaseBalance(memberWallet,award,TransactionType.HDC_EXCHANGE_FEE);
                    }
                    //存储hdc奖励
                    acChargeHdcAwardService.save(AcChargeHdcAward.builder()
                            .memberId(member.getId())
                            .fail(fail)
                            .status(status)
                            .memberStarPeople(data.getPeople())
                            .memberStar(member.getMemberStar())
                            .unitNumber(data.getUnitNumber())
                            .ratio(data.getRatio())
                            .sumAwardNumber(data.getSumAwardNumber())
                            .sumCount(data.getSumCount())
                            .awardHdc(data.getUnitNumber())
                            .build());
                    logger.info("==========发放用户hdc手续费奖励完成========member_id{}",member.getId());
                    return true;
                } catch (Exception exception) {
                    logger.info("执行事务异常，需要回滚");
                    transactionStatus.setRollbackOnly();
                    return false;
                }
            });
        }
        logger.info("========发放hdc手续费奖励结束========");
        //重置手续费奖励基数
        AcAwardConfig acAwardConfig = acAwardConfigMapper.selectOne(Wrappers.<AcAwardConfig>lambdaQuery().eq(AcAwardConfig::getName, SysConstant.DEAL_CHARGE_AWARD_NUMBER));
        acAwardConfig.setValue("0");
        acAwardConfigMapper.updateById(acAwardConfig);
        logger.info("========重置手续费奖励基数========");
    }

    /**
     * 获得每个星级和
     * @return
     */
    private Map<Integer,ChargeData> getStarRatioData(){
        //查询奖励总数配置
        AcAwardConfig acAwardConfig = acAwardConfigMapper.selectOne(Wrappers.<AcAwardConfig>lambdaQuery().eq(AcAwardConfig::getName,SysConstant.DEAL_CHARGE_AWARD_NUMBER));
        if(Objects.isNull(acAwardConfig)){
            log.info("===========未配置手续费奖励基数=========");
            throw new RuntimeException("未配置手续费奖励基数");
        }
        if(StringUtils.isEmpty(acAwardConfig.getValue())||Double.parseDouble(acAwardConfig.getValue())<=0){
            log.info("===========未设置总手续费=========");
            throw new RuntimeException("未设置总手续费");
        }
        log.info("===========手续费奖励基数配置参数=========,value:{}",acAwardConfig.getValue());
        BigDecimal hdcToday = BigDecimal.valueOf(Double.parseDouble(acAwardConfig.getValue()));
        //查询每个星级对应数量
        List<MemberStarCountDTO> memberCountList = memberMapper.findMemberCount();
        Map<Integer,ChargeData> map = Maps.newConcurrentMap();
        for(MemberStarCountDTO memberCount:memberCountList){
            map.put(memberCount.getMemberStar(),getChargeData(memberCountList,hdcToday,memberCount));
        }
        return map;
    }
    @lombok.Data
    @Builder
    static class ChargeData{
        //节点（星）类型人数*对应份数
        private Integer people;
        //该节点对应的奖励比例（星级对应的奖励比例）
        private BigDecimal ratio;
        //每个等级分配总和 = HDC * A %
        private BigDecimal sumCount;
        //奖励总数量
        private BigDecimal sumAwardNumber;
        //对应等级个人分配数量= 等级分配总合/对应等级人数
        private BigDecimal unitNumber;
    }

    private ChargeData getChargeData(List<MemberStarCountDTO> memberCountList,BigDecimal hdcToday,MemberStarCountDTO memberCount){
        StarChargeEnum stars = StarChargeEnum.getByOneLevel(memberCount.getMemberStar());
        //当前星级份数
        int starCount = MemberStarEnum.getByLevel(memberCount.getMemberStar()).getCount();
        //总份数
        int countAmount = 0;
        List<MemberStarCountDTO> list = memberCountList.stream().filter(s -> stars.getLevel().contains(s.getMemberStar())).collect(Collectors.toList());
        for (MemberStarCountDTO starCountDTO : list){
            //每个星级的份数：星级人数 * 对应份数
            int count = starCountDTO.getPepole() * MemberStarEnum.getByLevel(starCountDTO.getMemberStar()).getCount();
            countAmount = countAmount + count;
        }
//                .stream().mapToInt(MemberStarCountDTO::getPepole).sum();
        //每个等级分配总和 = HDC * A %
        BigDecimal multiply = hdcToday.multiply(stars.getRatio());
        //对应等级个人分配数量= 等级分配总合/总份数
        BigDecimal unitNumber = multiply.multiply(BigDecimal.valueOf(starCount)).divide(BigDecimal.valueOf(countAmount),8,RoundingMode.DOWN);
        return ChargeData.builder()
                .people(countAmount)
                .ratio(stars.getRatio())
                .sumCount(multiply)
                .sumAwardNumber(hdcToday)
                .unitNumber(unitNumber)
                .build();
    }


    /**
     * 推荐手续费奖励发放
     * @param dateStr 该日期不传，默认是当前东八区时间的前一天，查询数据为0点到23:59:59
     */
    public void chargeAwardGrant(String dateStr){
        LocalDateTime start = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX);
        logger.info("===============推荐手续费奖励发放============");
        logger.info("开始时间：{}，结束时间：{}",start,end);
        if(StringUtils.isNotEmpty(dateStr)){
            start = LocalDateTime.of(LocalDate.parse(dateStr), LocalTime.MIN);
            end = LocalDateTime.of(LocalDate.parse(dateStr), LocalTime.MAX);
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //获取用户当天的交易完成订单---币币挂单（exchange_order）
        logger.info("=========开始查询所有用户交易流水HDC手续费========={}",System.currentTimeMillis());
        List<MemberHdcChargeVo>  list = acGroupChargeAwardService.getMemberChargeList(start.format(formatter),end.format(formatter));
        logger.info("=========查询所有用户交易流水HDC手续费结束========={}",System.currentTimeMillis());

        if(CollectionUtils.isEmpty(list)){
            logger.info("=========未查询到交易流水HDC========={}",System.currentTimeMillis());
            return;
        }
        List<Long> uids = list.stream().map(MemberHdcChargeVo::getMemberId).collect(Collectors.toList());
        List<MemberAllParentDto> memberAllParentDto = newMemberService.findAllParentById(uids);
        Map<Long,BigDecimal> map = list.stream().collect(Collectors.toMap(MemberHdcChargeVo::getMemberId,MemberHdcChargeVo::getChargeAmount));
        //每个用户发放奖励，添加奖励记录
        upgradeStarCharge(memberAllParentDto,map);
    }

    /**
     * 奖励推荐人（手续费奖励）
     * @param parentDtoList 用户and推荐人团队集合
     * @param hdcMap 用户交易手续费
     */
    public void upgradeStarCharge(List<MemberAllParentDto> parentDtoList, Map<Long,BigDecimal> hdcMap) {
        for (MemberAllParentDto parentDto:parentDtoList){
            if (CollectionUtils.isEmpty(parentDto.getParentId())) {
                log.info("未查询到推荐人，memberId:{}", parentDto.getId());
                continue;
            }
            saveChargeRecord(parentDto,parentDto.getParentId(),hdcMap.get(parentDto.getId()));
        }
    }

    /**
     * 存储记录表（手续费奖励）
     */
    public void saveChargeRecord(MemberAllParentDto member, List<MemberParentDTO> parentList,BigDecimal hdc) {
        log.info("=========奖励用户团队=========，member_id{}",member.getId());
        log.info("=========奖励基数=========，hdcNumber{}",hdc);
        parentList = parentList.stream().sorted(Comparator.comparing(MemberParentDTO::getId).reversed()).collect(Collectors.toList());
        int level = 0;//当前奖励星级
        BigDecimal subtract = BigDecimal.ZERO; //需要减去比例
        BigDecimal residue = BigDecimal.valueOf(0.6);//剩余奖励比例
        if(Objects.nonNull(member.getMemberStar())&&member.getMemberStar().getLevel()>0){
            parentList.add(0,MemberParentDTO.builder().memberStar(member.getMemberStar().getLevel()).id(member.getId()).build());
        }
        //循环根据星级判断获取奖励百分比
        for(MemberParentDTO memberParentDTO:parentList){
            if(residue.compareTo(BigDecimal.valueOf(0))<=0){//如果剩余比例小于等于0，不再执行
                break;
            }
            if(memberParentDTO.getMemberStar()<=level){//等级小于等于上次奖励等级，直接跳过
                log.info("推荐人星级小于上一级推荐人等级，memberInfo:{}",memberParentDTO);
                continue;
            }
            log.info("=========奖励推荐人=========，to_member_id{}",memberParentDTO.getId());
            //获取当前星级奖励枚举
            ChargeRecommendEnum chargeRecommendEnum = ChargeRecommendEnum.getByLevel(memberParentDTO.getMemberStar());
            //计算当前人获得奖励，添加奖励记录  （奖励比例-已发放比例）
            BigDecimal ratio = chargeRecommendEnum.getRatio().subtract(subtract);
            if(ratio.compareTo(residue)>0){//如果奖励比例比剩余比例多，奖励比例则为剩余比例
                ratio = residue;
                residue = BigDecimal.ZERO;
            }
            log.info("=========奖励比例=========，ratio{}",ratio);
            //修改需要减去比例
            subtract = subtract.add(ratio);
            log.info("=========下个奖励人需要减去比例=========，subtract{}",subtract);
            //修改上次奖励星级
            level = memberParentDTO.getMemberStar();
            log.info("=========当前奖励星级=========，level{}",level);
            //修改当前剩余比例
            residue = residue.subtract(ratio);
            log.info("=========剩余比例=========，residue{}",residue);
            saveChargeRecord(hdc,ratio,memberParentDTO, member.getId());
            log.info("=========奖励发放完成=========，residue{}",residue);
        }
    }

    private void saveChargeRecord(BigDecimal hdc,BigDecimal ratio,MemberParentDTO memberParentDTO,Long memberId){
        OtcCoin otcCoin = new OtcCoin();
        otcCoin.setUnit("HDC");
        //消费hdc * （奖励比例-已发放比例）
        BigDecimal award = hdc.multiply(ratio).setScale(8, RoundingMode.DOWN);
        //添加奖励记录
        MemberWallet memberWallet = memberWalletService.findByOtcCoinAndMemberId(otcCoin, memberParentDTO.getId());
        //创建事务发放
        transactionTemplate.execute((TransactionCallback) transactionStatus -> {
            try {
                String fail = null;
                int status = 1;
                if(Objects.isNull(memberWallet)){
                    fail ="用户没有HDC钱包";
                    status = 0;
                }else{
                    memberWalletService.operateIncreaseBalance(memberWallet,award,TransactionType.GROUP_EXCHANGE_FEE);
                }
                //存储hdc奖励
                acGroupChargeAwardService.save(AcGroupChargeAward.builder()
                        .memberId(memberId)
                        .toMemberId(memberParentDTO.getId())
                        .toMemberStar(memberParentDTO.getMemberStar())
                        .proportion(ratio)
                        .money(hdc)
                        .number(award)
                        .fail(fail)
                        .status(status)
                        .build());
                return true;
            } catch (Exception exception) {
                log.info("执行事务异常，需要回滚");
                transactionStatus.setRollbackOnly();
                return false;
            }
        });
    }


}
